package com.weiyi.weiman.service.comics.impl;

import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.weiyi.weiman.domain.Const.ComicsConst;
import com.weiyi.weiman.domain.status.ResultStatus;
import com.weiyi.weiman.exception.APIException;
import com.weiyi.weiman.mapper.comics.ComicsChapterMapper;
import com.weiyi.weiman.mapper.comics.ComicsPictureMapper;
import com.weiyi.weiman.mapper.comics.ComicsMapper;
import com.weiyi.weiman.service.comics.ComicsUploadService;
import com.weiyi.weiman.utils.FastDFSUtils;
import com.weiyi.weiman.utils.RedisUtils;
import comics.Comics;
import comics.ComicsChapter;
import comics.ComicsPicture;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @Author
 * @Date 2021/5/6 下午11:12
 * @Description
 * @Version 1.0
 **/
@Service
@Slf4j
public class ComicsUploadServiceImpl implements ComicsUploadService {

    @Autowired
    private ComicsMapper comicsMapper;
    @Autowired
    private ComicsChapterMapper chapterMapper;
    @Autowired
    private ComicsPictureMapper pictureMapper;
    @Autowired
    private FastDFSUtils fastDFSUtils;
    @Autowired
    private RedisUtils redisUtils;

    @Override
    public boolean insert(Comics comics) {
        return comicsMapper.insert(comics) == 1 ? true : false;
    }

    @Override
    public boolean isExists(long comicsId) {
        return comicsMapper.isExists(comicsId) == 1 ? true : false;
    }

    /**
     * 上传一个章节的漫画图片
     * @param chapter
     * @param folderPath
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<ComicsPicture> uploadChapter(ComicsChapter chapter, String folderPath) {
        List<String> addressList = new ArrayList<>();
        long comicsId = chapter.getComicsId();
        if (!isExists(comicsId)) throw new APIException("漫画不存在");
        if (StringUtils.isEmpty(chapter.getChapterName()) || Objects.isNull(chapter.getChapterNum())) {
            throw new APIException("漫画章节名称为空");
        }
        QueryWrapper<ComicsChapter> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("comics_id", comicsId).eq("chapter_num", chapter.getChapterNum());
        if (!Objects.isNull(chapterMapper.selectOne(queryWrapper))) {
            throw new APIException("漫画章节已存在");
        }

        //上传章节相关信息
        int flag = chapterMapper.insert(chapter);
        if(flag != 1) {
            log.error(chapter.getChapterName() + " 章节写入数据库失败");
            throw new APIException(ResultStatus.DB_WRITE_ERROR);
        }

        //上传漫画图片
        if (StringUtils.isEmpty(folderPath)) {
            log.error("上传漫画文件路径为空");
            throw new APIException("漫画文件路径为空");
        }
        List<ComicsPicture> list = new ArrayList<>();
        File folder = new File(folderPath);
        for (File file : folder.listFiles()) {
            try {
                ComicsPicture comicsPicture = uploadPicture(file, chapter.getChapterId());
                addressList.add(comicsPicture.getPictureAddress());
                if (!Objects.isNull(comicsPicture) &&
                        pictureMapper.insert(comicsPicture) != 1) {
                    log.error(file.getName() + " 图片写入数据库失败");
                    deleteAll(addressList);
                    throw new APIException(ResultStatus.DB_WRITE_ERROR);
                }
                list.add(comicsPicture);
            } catch (Exception e) {
                log.error(file.getName()+" 文件上传失败", e);
                deleteAll(addressList);
                throw new APIException("文件上传失败");
            }
        }

        //如果章节封面为空，则默认采用上传的第一张图片
        if (StringUtils.isEmpty(chapter.getChapterCover())) {
            QueryWrapper<ComicsPicture> pictureQueryWrapper = new QueryWrapper<>();
            pictureQueryWrapper.eq("chapter_id", chapter.getChapterId())
                    .orderByAsc("picture_num");
            List<ComicsPicture> pictures = pictureMapper.selectList(pictureQueryWrapper);
            if (!Objects.isNull(pictures)) {
                ComicsPicture pic = pictures.get(0);
                chapter.setChapterCover(pic.getPictureAddress());
                chapterMapper.updateById(chapter);
            }
        }

        //修改漫画的章节信息
        Comics comics = comicsMapper.selectById(comicsId);
        comics.setComicsChapterNum(comics.getComicsChapterNum()+1);
        comicsMapper.updateById(comics);

        //将章节信息存入缓存中
        String chapterJson = JSON.toJSONString(chapter);
        redisUtils.lRightPushIfPresent(ComicsConst.CHAPTER_LIST_REDIS_PRE+comicsId, chapterJson);

        log.info(chapter.getChapterId() + "章节上传成功");
        return list;
    }

    /**
     * 上传图片
     * @param file
     * @return
     */
    private ComicsPicture uploadPicture(File file, long chapterId) throws Exception {
        String path = null;
        if (!Objects.isNull(file) && isImage(file)) {
            path = fastDFSUtils.uploadFile(file);
            int pictureNum = Integer.parseInt(file.getName().split("\\.")[0]);
            ComicsPicture comicsPicture = new ComicsPicture();
            comicsPicture.setChapterId(chapterId);
            comicsPicture.setPictureNum(pictureNum);
            comicsPicture.setPictureAddress(path);
            return comicsPicture;
        }
        return null;
    }

    /**
     * 判断文件是否是图片
     * @param file
     * @return
     */
    private boolean isImage(File file) {
        if (!file.exists()) {
            return false;
        }
        BufferedImage image = null;
        try {
            image = ImageIO.read(file);
            if (image == null || image.getWidth() <= 0 || image.getHeight() <= 0) {
                return false;
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    private void deleteAll(List<String> addressList) {
        for (String address : addressList) {
            fastDFSUtils.deleteFile(address);
            System.out.println(address+"已删除");
        }
    }
}
